package main

import (
	cdsa "crypto/dsa"
	"encoding/hex"
	"fmt"
	"github.com/gin-gonic/gin"
	"iss/security/des"
	"iss/security/dsa"
	"iss/security/hmac"
	"iss/security/md5"
	"iss/security/rc4"
	"iss/security/rsa"
	"iss/security/sha1"
	"iss/security/sha256"
	"iss/security/sha512"
	"log"
	"math/big"
	"net/http"
	"strconv"
	"strings"
)

// HTTP成功代码
const SuccessCode = 200

// HTTP失败代码
const ErrorCode = 400

func main() {
	run()
}

// Web服务器启动
func run() {
	r := gin.Default()
	r.Use(Cors())

	// sha1编码
	r.POST("/sha1", func(ctx *gin.Context) {
		shaParamBody := HashParam{}
		err := ctx.BindJSON(&shaParamBody)
		if err != nil {
			ctx.JSON(ErrorCode, gin.H{
				"status":  "error",
				"message": "解析错误",
				"data":    "",
			})
		} else {
			result := sha1.GetSHA1Encode(shaParamBody.Data, shaParamBody.Salt...)
			ctx.JSON(SuccessCode, gin.H{
				"status":  "success",
				"message": "SHA1加密字符串完成",
				"data":    result,
			})
		}
	})

	// sha256编码
	r.POST("/sha256", func(ctx *gin.Context) {
		shaParamBody := HashParam{}
		err := ctx.BindJSON(&shaParamBody)
		if err != nil {
			ctx.JSON(ErrorCode, gin.H{
				"status":  "error",
				"message": "解析错误",
				"data":    "",
			})
		} else {
			result := sha256.GetSHA256Encode(shaParamBody.Data, shaParamBody.Salt...)
			ctx.JSON(SuccessCode, gin.H{
				"status":  "success",
				"message": "SHA256加密字符串完成",
				"data":    result,
			})
		}
	})

	// sha224编码
	r.POST("/sha224", func(ctx *gin.Context) {
		shaParamBody := HashParam{}
		err := ctx.BindJSON(&shaParamBody)
		if err != nil {
			ctx.JSON(ErrorCode, gin.H{
				"status":  "error",
				"message": "解析错误",
				"data":    "",
			})
		} else {
			result := sha256.GetSHA224Encode(shaParamBody.Data, shaParamBody.Salt...)
			ctx.JSON(SuccessCode, gin.H{
				"status":  "success",
				"message": "SHA224加密字符串完成",
				"data":    result,
			})
		}
	})

	// sha512编码
	r.POST("/sha512", func(ctx *gin.Context) {
		shaParamBody := HashParam{}
		err := ctx.BindJSON(&shaParamBody)
		if err != nil {
			ctx.JSON(ErrorCode, gin.H{
				"status":  "error",
				"message": "解析错误",
				"data":    "",
			})
		} else {
			result := sha512.GetSHA512Encode(shaParamBody.Data, shaParamBody.Salt...)
			ctx.JSON(SuccessCode, gin.H{
				"status":  "success",
				"message": "SHA512加密字符串完成",
				"data":    result,
			})
		}
	})

	// SHA384加密字符串
	r.POST("/sha384", func(ctx *gin.Context) {
		shaParamBody := HashParam{}
		err := ctx.BindJSON(&shaParamBody)
		if err != nil {
			ctx.JSON(ErrorCode, gin.H{
				"status":  "error",
				"message": "解析错误",
				"data":    "",
			})
		} else {
			result := sha512.GetSHA384Encode(shaParamBody.Data, shaParamBody.Salt...)
			ctx.JSON(SuccessCode, gin.H{
				"status":  "success",
				"message": "SHA384加密字符串完成",
				"data":    result,
			})
		}
	})

	// md5加密字符串(32位)
	r.POST("/md5", func(ctx *gin.Context) {
		hashParamBody := HashParam{}
		err := ctx.BindJSON(&hashParamBody)
		if err != nil {
			ctx.JSON(ErrorCode, gin.H{
				"status":  "error",
				"message": "解析错误",
				"data":    "",
			})
		} else {
			result := md5.GetMD5Encode(hashParamBody.Data, hashParamBody.Salt...)
			ctx.JSON(SuccessCode, gin.H{
				"status":  "success",
				"message": "MD5加密字符串完成(32位)",
				"data":    result,
			})
		}
	})

	// md5加密字符串(16位)
	r.POST("/md5/16", func(ctx *gin.Context) {
		hashParamBody := HashParam{}
		err := ctx.BindJSON(&hashParamBody)
		if err != nil {
			ctx.JSON(ErrorCode, gin.H{
				"status":  "error",
				"message": "解析错误",
				"data":    "",
			})
		} else {
			result := md5.Get16MD5Encode(hashParamBody.Data)
			ctx.JSON(SuccessCode, gin.H{
				"status":  "success",
				"message": "MD5加密字符串完成(16位)",
				"data":    result,
			})
		}
	})

	// HMAC编码字符串
	r.POST("/hmac", func(ctx *gin.Context) {
		hmacParamBody := HmacParamBody{}
		err := ctx.BindJSON(&hmacParamBody)
		if err != nil {
			ctx.JSON(ErrorCode, gin.H{
				"status":  "error",
				"message": "解析错误",
				"data":    "",
			})
		} else {
			result := hmac.HMAC(hmacParamBody.Data, hmacParamBody.Key)
			ctx.JSON(SuccessCode, gin.H{
				"status":  "success",
				"message": "HMAC编码字符串",
				"data":    result,
			})
		}
	})

	// RC4加密
	r.POST("/rc4/encrypt", func(ctx *gin.Context) {
		ed := RC4Param{}
		err := ctx.BindJSON(&ed)
		if err != nil {
			ctx.JSON(ErrorCode, gin.H{
				"status":  "error",
				"message": "解析错误",
				"data":    "",
			})
		} else {
			plain := ed.Plain
			key := ed.Key
			log.Printf("RC4加密参数 Plain: %s, Key: %s\n", plain, key)

			encrypt := rc4.Encrypt([]byte(plain), []byte(key))
			result := BytesToInts(encrypt)
			log.Println(result)
			ctx.JSON(SuccessCode, gin.H{
				"status":  "success",
				"message": "RC4加密完成",
				"data":    result,
			})
		}
	})

	// RC4解密
	r.POST("/rc4/decrypt", func(ctx *gin.Context) {
		ed := RC4Param{}
		err := ctx.BindJSON(&ed)
		if err != nil {
			ctx.JSON(ErrorCode, gin.H{
				"status":  "error",
				"message": "解析错误",
				"data":    "",
			})
		} else {
			cipher := IntsToBytes(ed.Cipher)
			key := ed.Key
			log.Println("RC4解密密文: ", cipher)
			log.Println("RC4解密密钥: ", key)

			result := rc4.Decrypt(cipher, []byte(key))
			log.Println("RC4解密原始字节数组: ", result)
			out := string(result)
			log.Println("RC4解密结果: ", out)

			ctx.JSON(SuccessCode, gin.H{
				"status":  "success",
				"message": "RC4解密完成",
				"data":    out,
			})
		}
	})

	// DSA生成密钥对
	r.POST("/dsa/gen", func(ctx *gin.Context) {
		prvKey, pubKey := dsa.GenerateKey()
		log.Printf("DSA生成公钥和私钥:\n"+
			"公钥: %s\n"+
			"私钥: %s\n", pubKey, prvKey)
		ctx.JSON(SuccessCode, gin.H{
			"status":  "success",
			"message": "DSA生成密钥对完成",
			"prvKey":  prvKey,
			"pubKey":  pubKey,
			"customPubKey": DsaPublicKey{
				pubKey.P.String(),
				pubKey.Q.String(),
				pubKey.G.String(),
				pubKey.Y.String(),
			},
			"customPrvKey": DsaPrivateKey{
				prvKey.P.String(),
				prvKey.Q.String(),
				prvKey.G.String(),
				prvKey.Y.String(),
				prvKey.X.String(),
			},
		})
	})

	// DSA签名
	r.POST("/dsa/sign", func(ctx *gin.Context) {
		dsaParamBody := DsaParamBody{}
		err := ctx.BindJSON(&dsaParamBody)
		if err != nil {
			ctx.JSON(ErrorCode, gin.H{
				"status":  "error",
				"message": "解析错误",
				"data":    "",
			})
		} else {
			pk := dsaParamBody.PrvKey

			p, _ := strconv.ParseInt(pk.P, 10, 64)
			q, _ := strconv.ParseInt(pk.Q, 10, 64)
			g, _ := strconv.ParseInt(pk.G, 10, 64)
			y, _ := strconv.ParseInt(pk.Y, 10, 64)
			x, _ := strconv.ParseInt(pk.X, 10, 64)

			r, s := dsa.Sign(dsaParamBody.Msg, cdsa.PrivateKey{
				PublicKey: cdsa.PublicKey{
					Parameters: cdsa.Parameters{
						P: big.NewInt(p),
						Q: big.NewInt(q),
						G: big.NewInt(g),
					},
					Y: big.NewInt(y),
				},
				X: big.NewInt(x),
			})
			ctx.JSON(SuccessCode, gin.H{
				"status":  "success",
				"message": "DSA签名完成",
				"r":       r,
				"s":       s,
			})
		}
	})

	// DSA验证
	r.POST("/dsa/verify", func(ctx *gin.Context) {
		dsaParamBody := DsaParamBody{}
		err := ctx.BindJSON(&dsaParamBody)
		if err != nil {
			ctx.JSON(ErrorCode, gin.H{
				"status":  "error",
				"message": "解析错误",
				"data":    "",
			})
		} else {
			pk := dsaParamBody.PubKey

			p, _ := strconv.ParseInt(pk.P, 10, 64)
			q, _ := strconv.ParseInt(pk.Q, 10, 64)
			g, _ := strconv.ParseInt(pk.G, 10, 64)
			y, _ := strconv.ParseInt(pk.Y, 10, 64)
			//x, _ := strconv.ParseInt(pk.X, 10, 64)

			//verify := dsa.Verify(dsaParamBody.Msg, dsaParamBody.PubKey, dsaParamBody.R, dsaParamBody.S)
			verify := dsa.Verify(dsaParamBody.Msg, cdsa.PublicKey{
				Parameters: cdsa.Parameters{
					P: big.NewInt(p),
					Q: big.NewInt(q),
					G: big.NewInt(g),
				},
				Y: big.NewInt(y),
			}, dsaParamBody.R, dsaParamBody.S)

			if verify {
				ctx.JSON(SuccessCode, gin.H{
					"status":  "success",
					"verify":  verify,
					"message": "DSA验证通过, 数据签名未被篡改.",
				})
			} else {
				ctx.JSON(SuccessCode, gin.H{
					"status":  "success",
					"verify":  verify,
					"message": "DSA失败, 数据签名已被篡改.",
				})
			}
		}
	})

	// DES加密, 密钥8位
	r.POST("/des/encrypt", func(ctx *gin.Context) {
		desParamBody := DesParam{}
		err := ctx.BindJSON(&desParamBody)
		if err != nil {
			ctx.JSON(ErrorCode, gin.H{
				"status":  "error",
				"message": "解析错误",
				"data":    "",
			})
		} else {
			plain := desParamBody.Plain
			key := desParamBody.Key
			log.Printf("DES加密参数, plain: %s, key: %s\n", plain, key)
			result := des.Encrypt([]byte(plain), []byte(key))
			log.Println("DES加密结果: ", result)
			ctx.JSON(SuccessCode, gin.H{
				"status":  "success",
				"message": "DES算法加密完成",
				"data":    result,
			})
		}
	})

	// DES解密, 密钥8位
	r.POST("/des/decrypt", func(ctx *gin.Context) {
		desParamBody := DesParam{}
		err := ctx.BindJSON(&desParamBody)
		if err != nil {
			ctx.JSON(ErrorCode, gin.H{
				"status":  "error",
				"message": "解析错误",
				"data":    "",
			})
		} else {
			cipher := desParamBody.Cipher
			key := desParamBody.Key
			log.Printf("DES解密参数, cipher: %s, key: %s\n", cipher, key)
			result := des.Decrypt(cipher, []byte(key))
			log.Println("DES解密结果: ", result)
			ctx.JSON(SuccessCode, gin.H{
				"status":  "success",
				"message": "DES算法解密完成",
				"data":    result,
			})
		}
	})

	// RSA生成密钥对
	r.POST("/rsa/gen", func(ctx *gin.Context) {
		prvKey, pubKey := rsa.GenRsaKey()
		ctx.JSON(SuccessCode, gin.H{
			"status":  "success",
			"message": "RSA密钥对生成完成",
			"prvKey":  prvKey,
			"pubKey":  pubKey,
		})
	})

	// RSA加密
	r.POST("/rsa/encrypt", func(ctx *gin.Context) {
		rsaParam := RsaParam{}
		err := ctx.BindJSON(&rsaParam)
		if err != nil {
			ctx.JSON(ErrorCode, gin.H{
				"status":  "error",
				"message": "解析错误",
				"data":    "",
			})
		} else {
			plain := rsaParam.Plain
			pubKey := rsaParam.PubKey
			result := rsa.Encrypt([]byte(plain), pubKey)
			out := hex.EncodeToString(result)
			log.Printf("RSA加密 result: %s, out: %s\n", result, out)
			ctx.JSON(SuccessCode, gin.H{
				"status":  "success",
				"message": "RSA算法加密完成",
				"data":    out,
			})
		}
	})

	// RSA解密
	r.POST("/rsa/decrypt", func(ctx *gin.Context) {
		rsaParam := RsaParam{}
		err := ctx.BindJSON(&rsaParam)
		if err != nil {
			ctx.JSON(ErrorCode, gin.H{
				"status":  "error",
				"message": "解析错误",
				"data":    "",
			})
		} else {
			cipher := rsaParam.Cipher
			prvKey := rsaParam.PrvKey
			result := rsa.Decrypt([]byte(cipher), prvKey)
			out := string(result)
			log.Printf("RSA解密 result: %s, out: %s\n", result, out)
			ctx.JSON(SuccessCode, gin.H{
				"status":  "success",
				"message": "RSA算法解密完成",
				"data":    out,
			})
		}
	})

	// RSA数据签名
	r.POST("/rsa/sign", func(ctx *gin.Context) {
		rsaParam := RsaParam{}
		err := ctx.BindJSON(&rsaParam)
		if err != nil {
			ctx.JSON(ErrorCode, gin.H{
				"status":  "error",
				"message": "解析错误",
				"data":    "",
			})
		} else {
			message := rsaParam.Message
			prvKey := rsaParam.PrvKey
			result := rsa.SignWithSha256([]byte(message), prvKey)
			ctx.JSON(SuccessCode, gin.H{
				"status":  "success",
				"message": "RSA签名完成",
				"data":    hex.EncodeToString(result),
			})
		}
	})

	// RSA数据验证
	r.POST("/rsa/verify", func(ctx *gin.Context) {
		rsaParam := RsaParam{}
		err := ctx.BindJSON(&rsaParam)
		if err != nil {
			ctx.JSON(ErrorCode, gin.H{
				"status":  "error",
				"message": "解析错误",
				"data":    "",
			})
		} else {
			message := rsaParam.Message
			signData := rsaParam.SignData
			pubKey := rsaParam.PubKey
			verify := rsa.VerySignWithSha256([]byte(message), []byte(signData), pubKey)

			if verify {
				ctx.JSON(SuccessCode, gin.H{
					"status":  "success",
					"message": "RSA数据签名验证通过",
					"data":    verify,
				})
			} else {
				ctx.JSON(ErrorCode, gin.H{
					"status":  "error",
					"message": "RSA数据签名验证失败.",
					"data":    verify,
				})
			}
		}
	})

	_ = r.Run(":9981")
}

// 跨域处理
func Cors() gin.HandlerFunc {
	return func(c *gin.Context) {
		method := c.Request.Method               //请求方法
		origin := c.Request.Header.Get("Origin") //请求头部
		var headerKeys []string                  // 声明请求头keys
		for k, _ := range c.Request.Header {
			headerKeys = append(headerKeys, k)
		}
		headerStr := strings.Join(headerKeys, ", ")
		if headerStr != "" {
			headerStr = fmt.Sprintf("access-control-allow-origin, access-control-allow-headers, %s", headerStr)
		} else {
			headerStr = "access-control-allow-origin, access-control-allow-headers"
		}
		if origin != "" {
			c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
			c.Header("Access-Control-Allow-Origin", "*")                                       // 这是允许访问所有域
			c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE") //服务器支持的所有跨域请求的方法,为了避免浏览次请求的多次'预检'请求
			//  header的类型
			c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,X_Requested_With,Accept, Origin, Host, Connection, Accept-Encoding, Accept-Language,DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Pragma")
			//              允许跨域设置                                                                                                      可以返回其他子段
			c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers,Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma,FooBar") // 跨域关键设置 让浏览器可以解析
			c.Header("Access-Control-Max-Age", "172800")                                                                                                                                                           // 缓存请求信息 单位为秒
			c.Header("Access-Control-Allow-Credentials", "false")                                                                                                                                                  //  跨域请求是否需要带cookie信息 默认设置为true
			c.Set("content-type", "application/json")                                                                                                                                                              // 设置返回格式是json
		}

		//放行所有OPTIONS方法
		if method == "OPTIONS" {
			c.JSON(http.StatusOK, "Options Request!")
		}
		// 处理请求
		c.Next() //  处理请求
	}
}

// 字节数组转整数数组
func BytesToInts(data []byte) []int {
	result := make([]int, len(data))
	for index := range data {
		result[index] = int(data[index])
	}
	return result
}

// 整数数组转字节数组
func IntsToBytes(data []int) []byte {
	result := make([]byte, len(data))
	for index := range result {
		result[index] = byte(data[index])
	}
	return result
}

// RC4加密和解密JSON结构体
type RC4Param struct {
	Plain  string `json:"plain"`
	Key    string `json:"key"`
	Cipher []int  `json:"cipher"`
}

// DES加密和解密JSON结构体
type DesParam struct {
	Plain  string `json:"plain"`
	Key    string `json:"key"`
	Cipher string `json:"cipher"`
}

// AES加密和解密JSON结构体
type AesParam struct {
	Plain  string `json:"plain"`
	Key    string `json:"key"`
	Cipher []int  `json:"cipher"`
}

// RSA JSON结构体
type RsaParam struct {
	PrvKey   []byte `json:"prvKey"`
	PubKey   []byte `json:"pubKey"`
	Plain    string `json:"plain"`
	Cipher   string `json:"cipher"`
	Message  string `json:"message"`
	SignData string `json:"signData"`
}

// Hash操作JSON结构体
type HashParam struct {
	Data string   `json:"data"`
	Salt []string `json:"salt"`
}

// HMAC JSON结构体
type HmacParamBody struct {
	Data string `json:"data"`
	Key  string `json:"key"`
}

// DSA签名和验证JSON结构体
type DsaParamBody struct {
	//PubKey cdsa.PublicKey  `json:"pubKey"`
	//PrvKey cdsa.PrivateKey `json:"prvKey"`
	PubKey DsaPublicKey  `json:"pubKey"`
	PrvKey DsaPrivateKey `json:"prvKey"`
	Msg    string        `json:"msg"`
	R      *big.Int      `json:"r"`
	S      *big.Int      `json:"s"`
	//CustomPubKey DsaPublicKey `json:"customPubKey"`
	//CustomPrvKey DsaPrivateKey `json:"customPrvKey"`
}

type DsaPublicKey struct {
	P, Q, G, Y string
}

type DsaPrivateKey struct {
	P, Q, G, Y, X string
}
